Skip to content

Feature: Handle symbol-to-proc wrappers (&:) that refer to a method created using delegation or method missing#406

Merged
numbata merged 6 commits into
ruby-grape:masterfrom
marcrohloff:feature/support-ampersand-blocks-for-delegated-methods
Jun 2, 2026
Merged

Feature: Handle symbol-to-proc wrappers (&:) that refer to a method created using delegation or method missing#406
numbata merged 6 commits into
ruby-grape:masterfrom
marcrohloff:feature/support-ampersand-blocks-for-delegated-methods

Conversation

@marcrohloff
Copy link
Copy Markdown
Contributor

@marcrohloff marcrohloff commented May 8, 2026

Summary

Improve handling of symbol-to-proc exposure blocks (&:method_name) for delegated and dynamically dispatched methods.

Previously grape-entity eagerly validated method arity for &:method_name blocks. This worked for ordinary methods, but produced incorrect behavior for methods implemented via delegate or method_missing, where Ruby may expose ambiguous or negative arity values.

This PR makes arity validation more conservative and Ruby-compatible:

  • continue raising curated errors for ordinary methods with required arguments
  • correctly allow methods with only optional args/splats/kwargs
  • gracefully handle delegated and method_missing-backed methods
  • fall back to Ruby's native runtime errors when introspection is unreliable

Changes

  • tighten symbol-to-proc wrapper detection
  • add positional_arity_for helper for normalized arity handling
  • support optional positional/keyword arguments correctly
  • avoid false positives for delegation wrappers and dynamic dispatch
  • add extensive spec coverage for delegation, method_missing, splats, kwargs, and edge cases

Backward Compatibility

Public API is unchanged.

The only observable behavior change is that delegated or dynamic-dispatch methods may now raise Ruby-native errors instead of grape-entity-generated arity errors when the callable contract cannot be reliably introspected.

@marcrohloff marcrohloff force-pushed the feature/support-ampersand-blocks-for-delegated-methods branch from 2b8851e to be995c1 Compare May 8, 2026 15:43
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 9, 2026

Danger Report

No issues found.

View run

@dblock dblock requested a review from numbata May 10, 2026 23:56
Copy link
Copy Markdown
Collaborator

@numbata numbata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcrohloff Thanks for the contribution! The motivation is solid. 👍

Two things to address before merging: the arity <= 0 guard is too wide (see inline comment), and the new method_missing in the shared fixture risks making the "undefined method" test fragile. Left suggestions on both.

Comment thread lib/grape_entity/entity.rb Outdated
Comment thread CHANGELOG.md Outdated
Comment thread CONTRIBUTING.md Outdated
Comment thread spec/grape_entity/entity_spec.rb Outdated
Comment thread spec/grape_entity/entity_spec.rb
@marcrohloff marcrohloff requested a review from numbata May 13, 2026 21:53
Comment thread lib/grape_entity/entity.rb Outdated
Comment thread spec/grape_entity/entity_spec.rb Outdated
@marcrohloff marcrohloff requested a review from numbata June 1, 2026 17:07
marcrohloff and others added 5 commits June 2, 2026 00:18
… created using delegation or method missing

These methods have an arity of -1
Add argumenterror specs
… specs

Fixes arity math for variadic methods, skips methods with required keyword
arguments, extracts positional_arity_for for clarity, and adds specs for
optional kwargs, splats, private methods, delegation, and a canary for the
Proc#to_s regex. Also pins the ActiveSupport delegation require in spec_helper
and moves the CHANGELOG entry under Fixes.
@numbata numbata force-pushed the feature/support-ampersand-blocks-for-delegated-methods branch from d8f4809 to a4d280f Compare June 2, 2026 13:45
@numbata
Copy link
Copy Markdown
Collaborator

numbata commented Jun 2, 2026

Thanks for taking my comments into account, @marcrohloff! I added a few improvements on top of your commits before merging:

  • Tightened the Proc#to_s regex to a strict anchored match to avoid false positives on non-symbol-to-proc lambdas
  • Fixed the arity math for variadic methods (def foo(req, *rest) was being miscounted)
  • Added a bail-out for required keyword arguments so Ruby surfaces its native "missing keyword" error rather than a
    misleading one from us
  • Extracted positional_arity_for to keep the arity introspection logic self-contained and testable
  • Expanded the spec coverage to include optional kwargs, splats, private methods, delegation-backed objects, and a canary spec for the Proc#to_s format the detection relies on

Great find, and thanks again for the PR! 👍

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves Grape::Entity’s handling of symbol-to-proc exposure blocks (&:method_name) when the underlying method is wrapped (e.g., ActiveSupport delegate) or dynamically handled (e.g., method_missing), where arity/introspection can be non-standard (including negative arity).

Changes:

  • Tighten detection/parsing of symbol-to-proc wrapper procs and adjust arity enforcement logic.
  • Add spec coverage for optional args, splats, private methods, method_missing, and delegate-backed methods.
  • Update test setup to load ActiveSupport delegation helpers and document the behavior in the changelog.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
spec/spec_helper.rb Requires ActiveSupport delegation extension to support delegate usage in specs.
spec/grape_entity/entity_spec.rb Adds/updates specs for &:method_name across optional args, private methods, method_missing, and delegate.
lib/grape_entity/entity.rb Refines symbol-to-proc wrapper parsing and arity enforcement, with a new helper for arity inspection.
CHANGELOG.md Adds an entry describing the feature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread spec/grape_entity/entity_spec.rb
Comment thread spec/grape_entity/entity_spec.rb Outdated
Comment thread lib/grape_entity/entity.rb Outdated
Comment thread CHANGELOG.md Outdated
Switches from Method#arity math to Method#parameters inspection for more
precise required-arg detection. Required keyword arguments now produce a
curated ArgumentError instead of falling through to Ruby's native error.
Adds a spec for the required-kwargs case and sharpens the delegation and
method_missing NOTE comments.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@numbata numbata merged commit 1f536e4 into ruby-grape:master Jun 2, 2026
7 checks passed
@rc-marc-rohloff
Copy link
Copy Markdown

@numbata Thanks for cleaning that up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants